﻿using UnityEngine;
using System.Collections;
using MoreMountains.Tools;

namespace MoreMountains.CorgiEngine
{
    /// <summary>
    /// Add this class to a character and it'll be able to perform a horizontal dash
    /// Animator parameters : Dashing
    /// </summary>
    [AddComponentMenu("Corgi Engine/Character/Abilities/Character Dash")]
    public class CharacterDash : CharacterAbility
    {
        public override string HelpBoxText() { return "This component allows your character to dash. Here you can define the distance the dash should cover, how much force to apply, and the cooldown between the end of a dash and the start of the next one."; }

        [Header("Dash")]
        /// the duration of dash (in seconds)
        public float DashDistance = 3f;
        /// the force of the dash
        public float DashForce = 40f;
        /// the duration of the cooldown between 2 dashes (in seconds)
        public float DashCooldown = 1f;
        //  最大保持时间
        public float keepTime = 0.4f;

        //  是否只能在地面使用
        public bool OnlyCanUseInGroud = false;

        protected float _cooldownTimeStamp = 0;

        protected float _startTime;
        protected Vector3 _initialPosition;
        protected float _dashDirection;
        protected float _distanceTraveled = 0;
        protected bool _shouldKeepDashing = true;
        protected float _computedDashForce;

        protected override void Initialization()
        {
            base.Initialization();
        }

        protected override bool CheckHandleInput()
        {
            return _inputManager.DashButton.State.CurrentState == MMInput.ButtonStates.ButtonDown;

            //// If the user presses the dash button and is not aiming down
            //if (_inputManager.PrimaryMovement.y > -_inputManager.Threshold.y)
            //{

            //}
        }
        protected override void HandleInput()
        {
            StartDash();
        }


        /// <summary>
        /// The second of the 3 passes you can have in your ability. Think of it as Update()
        /// </summary>
        public override void ProcessAbility()
        {
            base.ProcessAbility();
            // If the character is dashing, we cancel the gravity
            if (_movement.CurrentState == CharacterStates.MovementStates.Dashing)
            {
                _controller.GravityActive(false);
                _controller.SetVerticalForce(0);
            }
        }

        /// <summary>
        /// Causes the character to dash or dive (depending on the vertical movement at the start of the dash)
        /// </summary>
        public virtual void StartDash()
        {
            // if the Dash action is enabled in the permissions, we continue, if not we do nothing
            if (!AbilityPermitted
                || (_condition.CurrentState != CharacterStates.CharacterConditions.Normal)
                || (_movement.CurrentState == CharacterStates.MovementStates.Gripping))
                return;

            if (OnlyCanUseInGroud && (_controller.State.IsGrounded == false))
                return;

            //  正处于自己这个状态时，返回
            if (_movement.CurrentState == CharacterStates.MovementStates.Dashing)
                return;

            // if the character is allowed to dash
            if (_cooldownTimeStamp <= Time.time)
            {
                // we set its dashing state to true
                _movement.ChangeState(CharacterStates.MovementStates.Dashing);

                // we start our sounds
                PlayAbilityStartSfx();
                PlayAbilityUsedSfx();

                _cooldownTimeStamp = Time.time + DashCooldown;
                // we launch the boost corountine with the right parameters
                StartCoroutine(Dash());
            }
        }

        /// <summary>
        /// Coroutine used to move the player in a direction over time
        /// </summary>
        protected virtual IEnumerator Dash()
        {
            // if the character is not in a position where it can move freely, we do nothing.
            if (!AbilityPermitted
                || (_condition.CurrentState != CharacterStates.CharacterConditions.Normal))
            {
                yield break;
            }

            //  禁用按键控制
            ControlInput(false);

            _startTime = Time.time;
            _initialPosition = this.transform.position;
            _distanceTraveled = 0;
            _shouldKeepDashing = true;
            _dashDirection = _character.IsFacingRight ? 1f : -1f;
            _computedDashForce = DashForce * _dashDirection;


            float timer = 0;
            while (_distanceTraveled < DashDistance && timer < keepTime) // && _shouldKeepDashing 
            {
                timer += Time.deltaTime;

                _distanceTraveled = Vector3.Distance(_initialPosition, this.transform.position);

                //if (_controller.State.IsCollidingLeft || _controller.State.IsCollidingRight)
                //{
                //    _shouldKeepDashing = false;
                //}

                _controller.GravityActive(false);

                _controller.SetVerticalForce(0);
                _controller.SetHorizontalForce(_computedDashForce);

                yield return null;
            }


            _controller.GravityActive(true);

            // we play our exit sound
            StopAbilityUsedSfx();
            PlayAbilityStopSfx();

            // once the boost is complete, if we were dashing, we make it stop and start the dash cooldown
            if (_movement.CurrentState == CharacterStates.MovementStates.Dashing)
            {
                //_movement.RestorePreviousState();
                _movement.ChangeState(CharacterStates.MovementStates.Idle); //  我设置成了变成站立。
            }

            //  恢复按键控制
            ControlInput(true);

            //_saveAblity.InvokeSavedEvent();
        }

        /// <summary>
        /// Adds required animator parameters to the animator parameters list if they exist
        /// </summary>
        protected override void InitializeAnimatorParameters()
        {
            RegisterAnimatorParameter("Dashing", AnimatorControllerParameterType.Bool);
        }

        /// <summary>
        /// At the end of the cycle, we update our animator's Dashing state 
        /// </summary>
        public override void UpdateAnimator()
        {
            MMAnimator.UpdateAnimatorBool(_animator, "Dashing", (_movement.CurrentState == CharacterStates.MovementStates.Dashing), _character._animatorParameters);
        }

    }
}